function ChildForceLayout(config){
	const {
		nodes,
		links,
		defs,
		menus,
		holderDom,
		edgeLink,
	} = config;
	this.nodes = nodes;
	this.links = links;
	this.defs = defs;
	this.menus = menus;
	this.holderDom = holderDom;
	
	this.simulation = d3.forceSimulation(this.nodes)
		.force("link",d3.forceLink(this.links).id(d=>d.id))
		.force("charge",d3.forceManyBody().strength(-300))
		.force("center",d3.forceCenter(width / 2, height / 2))
		.force("collide", d3.forceCollide(100).strength(0.2).iterations(5))
		.alphaDecay(0.0228);
		
	
		
	this.nodes.forEach(item=>{
		this.holderDom
			.insert("circle","circle:nth-child(1)")
			.attr("class","circleclass1")
			.attr("fill","url(#ava"+item.id+")")
			.attr("r",item.r)
			.attr("cx",item.x)
			.attr("cy",item.y)
			.attr("nodeid",item.id)
			.attr("stroke","#ccc")
			.attr("stroke-width",2);
	});
	this.nodeDom = this.holderDom
		.selectAll("circle.circleclass1");
		
	this.links.forEach(item=>{
		this.holderDom
			.insert("g","g:nth-child(1)")
			.attr("class","edge1")
			.attr("fill","#bad4ed")
			.attr("transform",this.getTransform(item.source, item.target, this.getDis(item.source, item.target)));
	});
	this.edgeDom = this.holderDom
			.selectAll("g.edge1");
			
	this.links.forEach(item=>{
		this.edgeDom
			.insert("path","path:nth-child(1)")
			.attr("class","links1")
			.style("marker-end", "url(#marker)")
			.attr("d","M3,0 L"+this.getDis(item.source, item.target)+",0")
			.attr("stroke","#bad4ed");
	});		
		this.edgeLink = this.edgeDom
			.selectAll("path.links1");
}

ChildForceLayout.prototype.init = function(){
	const _this = this;
	
	this.nodes.forEach(item=>{
		this.defs
			.insert("pattern","pattern:nth-child(1)")
			.attr("class","patternclass")
			.attr("id",item.id)
			.attr('patternUnits', 'objectBoundingBox')
			.attr("x", "0")
			.attr("y", "0")
			.attr("width", "1")
			.attr("height", "1");
	});
		
	const patterns = 
		this.defs
		.selectAll("pattern.patternclass");
	
	this.nodes.forEach(item=>{
		patterns.insert("image","image:nth-child(1)")
			.attr("xlink:href",item.pic)
			.attr("src",item.pic)
			.attr("width",item.r*2)
			.attr("height",item.r*2)
			.attr("preserveAspectRatio", "xMidYMin slice");
	});
		
	//this.simulation.on("tick", () => this.ticked());
	
	this.nodeDom
		.on("click",()=>{
			
		})
		.on("mouseover",function(){
			d3.select(this)
			.attr("stroke-width",6)
			.attr("stroke",'#c5dbf0');
		})
		.on("mouseout",function(){
			d3.select(this)
			.attr("stroke-width",2)
			.attr("stroke",'#ccc');
		})
		.on("contextmenu",function(){
			event = event || window.event;
			event.cancelBubble = true;
			event.returnValue = false;
			d3.event.preventDefault();//屏蔽右键菜单

			_this.menus.style("left",d3.select(this).attr("cx")+"px")
				.style("top",d3.select(this).attr("cy")+"px")
				.style("display","block");
			
			_this.menus.attr("parentid",d3.select(this).attr("nodeid"));
			
		})
		.call(
			d3.drag()
			.on("start",d=>this.dragStart(d))
			.on("end",d=>this.dragEnd(d))
			.on("drag",d=>this.draged(d))
		);
}
ChildForceLayout.prototype.dragStart = function(d){
	d3.event.sourceEvent.stopPropagation();
	if (!d3.event.active) this.simulation.alphaTarget(0.3).restart();
	d.fx = d.x;
    d.fy = d.y;
}
ChildForceLayout.prototype.dragEnd = function(d){
	if (!d3.event.active) this.simulation.alphaTarget(0);
	d.fx = null;
    d.fy = null;
}
ChildForceLayout.prototype.draged = function(d){
	d.fx = d3.event.x;
    d.fy = d3.event.y;
}
ChildForceLayout.prototype.ticked = function(){
	
	this.nodeDom.attr("cx",d=>d.x)
	.attr("cy",d=>d.y);
	//this.nodeDom.attr("cx",d=>{console.log(d);return d})
	
	this.edgeDom.attr("transform",d=>{
		return this.getTransform(d.source, d.target, this.getDis(d.source, d.target));
	});
	
	 this.edgeLink.attr("d", d => {
            return "M3,0 L"+this.getDis(d.source, d.target)+",0";
     });
}

// 求元素移动到目标位置所需要的 transform 属性值
ChildForceLayout.prototype.getTransform = function(source, target, _dis){
	var r;
    if (target.x > source.x) {
        if (target.y > source.y) {
            r = Math.asin((target.y - source.y) / _dis)
        } else {
            r = Math.asin((source.y - target.y) / _dis);
            r = -r;
        }
    } else {
        if (target.y > source.y) {
            r = Math.asin((target.y - source.y) / _dis);
            r = Math.PI - r;
        } else {
            r = Math.asin((source.y - target.y) / _dis);
            r -= Math.PI;
        }
    }
    r = r * (180 / Math.PI);
    return "translate(" + source.x + "," + source.y + ")rotate(" + r + ")";
}
ChildForceLayout.prototype.getDis = function(s, t){
	return Math.sqrt((s.x - t.x) * (s.x - t.x) + (s.y - t.y) * (s.y - t.y));
}

ChildForceLayout.prototype.addEdges = function(){
	
}
ChildForceLayout.prototype.addNodes = function(){
	
}
ChildForceLayout.prototype.addAva = function(){
	
}